﻿using System;
using System.Collections;
using System.IO;
using Launcher.Util;
using System.Diagnostics;
using wdwp.Desktop.widgetLib.CommonTypes;

namespace wdwp.Desktop.Launcher
{
    /// <summary>
    /// 위젯 소스의 정보를 담는 구조체 
    /// </summary>
    /// 
    /*
    public struct sWidgetInfo
    {
        public string Name;            //위젯 이름     
        public string FullHTMLUri;      //위젯 HTML 경로
        //string Author;          //제작자 정보
        //string Version;         //위젯 버전
        public string Type;            //위젯 타입 (실버라이트/플래쉬)

        public int Width;              //가로크기 
        public int Height;             //세로크기

        public sWidgetInfo(string strName, int nHeight, int nWidth, string strType, string Path)            
        {
            Name = strName;
            Height = nHeight;
            Width = nWidth;            
            Type = strType;

            FullHTMLUri = Path;
        }
    };
     * */

    /// <summary>
    /// 위젯 소스의 타입을 정의하는 열거형 
    /// </summary>
    public struct sTypes
    {
        public const string FLASH_WIDGET = "Flash";
        public const string AG_WIDGET = "Silverlight";
        public const string INVALID_WIDGET = "Invalid";
    };    

    /// <summary>
    /// 위젯 소스들을 탐색하고 관리 
    /// </summary>
    public class widgetSrcManager
    {
        
        ArrayList m_arWidgetSrcInfos;
        string    m_strWidgetSrcRoot;   


        /// <summary>
        /// 위젯을 로드하는 매니저를 실행시킵니다. 
        /// </summary>
        /// <param name="strWdgtSrcRoot">위젯 소스폴더들의 루트 디렉토리</param>
        public widgetSrcManager(string strWdgtSrcRoot)
        {
            m_arWidgetSrcInfos = new ArrayList();

            m_strWidgetSrcRoot = strWdgtSrcRoot;

            doSearch(strWdgtSrcRoot);            
        }


        /// <summary>
        /// 위젯정보를 재 검색하고 로드합니다. 
        /// </summary>
        public void refresh()
        {
            m_arWidgetSrcInfos.Clear();

            doSearch(m_strWidgetSrcRoot);
        }


        /// <summary>
        /// 주어진 폴더의 하위 폴더를 뒤지면서 소스가 존재하는지, 있다면 어느 타입인지 알아냅니다.
        /// </summary>
        /// <param name="strWdgtSrcRoot">위젯 소스폴더들의 루트 디렉토리</param>
        private void doSearch(string strWdgtSrcRoot)
        {            
            try
            {
                DirectoryInfo dirSrcRoot = new DirectoryInfo(strWdgtSrcRoot);

                DirectoryInfo[] srcDirs = dirSrcRoot.GetDirectories();
                if (srcDirs.Length == 0) throw new Exception("Cannot find any widget sub dirs");
                
                foreach (DirectoryInfo aSrcDir in srcDirs)
                {
                    string HTMLfilePath = "";
                    string Type = verifySrc(aSrcDir, ref HTMLfilePath);
                    

                    if (Type == sTypes.FLASH_WIDGET)
                    {
                        parseFlashHTML(HTMLfilePath);                        
                    }
                    else if (Type == sTypes.AG_WIDGET)
                    {
                        parseAgHTML(HTMLfilePath);                        
                    }
                    else                    
                    {
                        Debug.WriteLine("Invaild Type Src");
                    }                    
                }
            }
            catch (Exception exc)
            {
                Debug.WriteLine(exc.ToString());
            }
        }

        /// <summary>
        /// 위젯 소스의 타입을 분별함
        /// </summary>
        /// <param name="srcDir">소스파일들을 담고있는 폴더</param>
        /// <returns></returns>
        private string verifySrc(DirectoryInfo srcDir, ref string strHTMLPath)
        {          

            //flash - project이름.swf & project이름.html
            //silverlight - default.html & silverlight.js

            FileInfo[] JSfiles = srcDir.GetFiles("*.js");
            FileInfo[] SWFfiles = srcDir.GetFiles("*.swf");

            try
            {                   
                //실버라이트 위젯인가?
                foreach (FileInfo aFile in JSfiles)
                {
                    if (aFile.Name == "Silverlight.js")  //silverlight.js 파일이 있으면 실버라이트로 간주
                    {
                        strHTMLPath = aFile.DirectoryName + "\\default.html";
                        return sTypes.AG_WIDGET;
                    }
                }

                //플래쉬 위젯인가?

                JSfiles = srcDir.GetFiles("AC_RunActiveContent.js");

                foreach (FileInfo aFile in SWFfiles)  //SWF파일과 동일한 이름의 HTML이 있거나 AC_RunActiveContent 있으면 플래쉬로 간주
                {
                    FileInfo[] htmlFile = srcDir.GetFiles(aFile.Name.Substring(0, aFile.Name.Length - 4) + ".html");

                    if(htmlFile.Length > 0 && JSfiles.Length > 0)
                    {
                        strHTMLPath = htmlFile[0].FullName; //aFile.DirectoryName + "\\" + aFile.Name + ".html";
                        return sTypes.FLASH_WIDGET;
                    }
                }


                //모르는 타입인가?
                return sTypes.INVALID_WIDGET;                

            }
            catch (Exception exc)
            {                
                throw exc;
            }
        }

               

        /// <summary>
        /// Flash HTML 소스를 분석하여 필요한 정보를 추출합니다. 
        /// </summary>
        /// <param name="strSrcPath">Flash를 임베딩하고 있는 HTML소스</param>
        private void parseFlashHTML(string strSrcPath)
        {
            try
            {
                StreamReader sr = File.OpenText(strSrcPath);
                string HTMLText = sr.ReadToEnd();
                StringParser parser = new StringParser(HTMLText);

                //HTML안에서 위젯의 이름을 얻어냄
                string Name = "";

                HTMLText = StringParser.removeComments(HTMLText);
                parser = new StringParser(HTMLText);

                parser.skipToEndOfNoCase("<title>");
                parser.extractTo("</title>", ref Name);


                //HTML안에서 위젯의 크기를 얻어냄 
                string height = "", width = "";

                HTMLText = StringParser.removeComments(HTMLText);
                parser = new StringParser(HTMLText);

                parser.skipToEndOf("'width', '");
                parser.extractTo("',", ref width);

                parser.skipToEndOf("'height', '");
                parser.extractTo("',", ref height);

                width = width.Trim('\'');
                height = height.Trim('\'');

                Console.WriteLine("Name: {0}, width: {1}, height: {2}\n", Name, width, height);

                //생성한 구조체로 위젯을 리스트에 등록 
                regWidget(new sWidgetInfo(Name, int.Parse(height), int.Parse(width), sTypes.FLASH_WIDGET, strSrcPath));
            }
            catch (Exception exc)
            {
                throw exc;
            }
              
        }

        /// <summary>
        /// 실버라이트 HTML 소스를 분석하여 필요한 정보를 추출합니다. 
        /// </summary>
        /// <param name="strSrcPath">실버라이트를 임베딩하고 있는 HTML소스</param>
        private void parseAgHTML(string strSrcPath)
        {
            try
            {
                StreamReader sr = File.OpenText(strSrcPath);
                string HTMLText = sr.ReadToEnd();
                StringParser parser = new StringParser(HTMLText);

                //HTML안에서 위젯의 이름을 얻어냄
                string Name = "";

                HTMLText = StringParser.removeComments(HTMLText);
                parser = new StringParser(HTMLText);

                parser.skipToEndOfNoCase("<title>");
                parser.extractTo("</title>", ref Name);


                //HTML안에서 위젯의 크기를 얻어냄 
                string height = "", width = "";

                HTMLText = StringParser.removeHtml(HTMLText);
                parser = new StringParser(HTMLText);

                //for silverlight 1.0
                if (parser.skipToStartOf(".silverlightHost"))
                {
                    parser.skipToEndOf("height:");
                    parser.extractTo("px;", ref height);

                    parser.skipToEndOf("width:");
                    parser.extractTo("px;", ref width);
                }
                else //만일 HTML안에 스타일 설정이 없다면 JS 파일을 뒤짐 
                {                    
                    //for silverlight 0.98

                    sr = File.OpenText(strSrcPath + ".js");
                    HTMLText = sr.ReadToEnd();
                    HTMLText = StringParser.removeEnclosingQuotes(HTMLText);
                    parser = new StringParser(HTMLText);

                    parser.skipToEndOf("properties:");

                    parser.skipToEndOf("width: ");
                    parser.extractTo(",", ref width);

                    width = width.Trim('\"');

                    parser.skipToEndOf("height: ");
                    parser.extractTo(",", ref height);

                    height = height.Trim('\"');
                }

                Console.WriteLine("Name: {0}, width: {1}, height: {2}\n", Name, width, height);

                //생성한 구조체로 위젯을 리스트에 등록 
                regWidget(new sWidgetInfo(Name, int.Parse(height), int.Parse(width), sTypes.AG_WIDGET, strSrcPath));

            }
            catch (Exception exc)
            {
                throw exc;
            }
               
                        
        }


        /// <summary>
        /// 구조체의 정보를 가지고 위젯을 등록시킵니다.
        /// </summary>
        /// <param name="SrcInfo"></param>
        private bool regWidget(sWidgetInfo SrcInfo)
        {
            //동일한 이름의 위젯이 있는가 체크 
            foreach (sWidgetInfo aInfo in m_arWidgetSrcInfos)
            {
                if (aInfo.Name == SrcInfo.Name)
                {
                    Debug.WriteLine("Same widget exists" + aInfo.Name);
                    return false;
                }
            }

            m_arWidgetSrcInfos.Add(SrcInfo);
            return true;
        }


        /// <summary>
        /// 위젯의 이름을 가지고 등록된 위젯을 삭제합니다. 
        /// </summary>
        /// <param name="WidgetName">삭제할 위젯의 이름</param>
        public bool unRegWidget(string WidgetName)
        {
            //ArrayList를 탐색하면서 동일한 이름의 위젯을 찾음 
            //발견하면 인덱스를 가지고 이를 삭제 

            foreach (sWidgetInfo aInfo in m_arWidgetSrcInfos)
            {
                if (aInfo.Name == WidgetName)
                {
                    m_arWidgetSrcInfos.Remove(aInfo);
                    return true;
                }
            }

            Debug.WriteLine("Cannot find such Name in widgetInfo");
            return false;
        }


        /// <summary>
        /// 위젯들의 메타정보를 가지고 있는 리스트를 얻어옵니다. 
        /// </summary>
        public ArrayList WidgetSrcList
        {
            get
            {
                return m_arWidgetSrcInfos;
            }
        }          
         
    }

}